Módulo 2: Estructuración y manipulación de datos con Python#

El manejo de datos es el corazón de cualquier proyecto de análisis, y Python se ha consolidado como uno de los lenguajes más poderosos y versátiles para este propósito. En este módulo, nos sumergiremos en las técnicas fundamentales para la estructuración y manipulación de datos utilizando Python, proporcionando las bases necesarias para transformar datos crudos en información útil y procesable.

Comenzaremos explorando las estructuras de datos disponibles en Python, como listas, dataframes, pilas, colas, árboles y grafos. Estas estructuras permiten organizar y acceder a la información de manera eficiente, lo que es crucial cuando se trabaja con grandes volúmenes de datos o datos complejos. Además, abordaremos cómo manipular y transformar datos no estructurados, como textos, imágenes y datos provenientes de redes sociales, que requieren enfoques y herramientas específicas para su análisis.

El módulo también se centrará en el uso de librerías especializadas como NumPy y Pandas, que son esenciales para el análisis de datos en Python. Estas librerías ofrecen potentes funciones para la manipulación y el análisis de datos estructurados, permitiendo realizar operaciones avanzadas con facilidad y eficiencia.

Además, aprenderemos a trabajar con secuencias de datos utilizando herramientas como re, string e itertools, que son fundamentales para el procesamiento y análisis de cadenas de texto y otras secuencias de información. La habilidad para manipular secuencias es clave en tareas como la limpieza de datos y la preparación de datos para modelos de machine learning.

Finalmente, exploraremos las bases de la visualización de datos para representar de manera gráfica los resultados del análisis, facilitando la interpretación y comunicación de los hallazgos. Este módulo también incluirá casos prácticos que permitirán a los participantes aplicar las técnicas aprendidas en escenarios reales, consolidando así los conceptos y habilidades adquiridos.

Archivos planos con Numpy y Pandas#

En esta sección aprenderás a importar datos a Python desde todo tipo de archivos planos, que son una forma sencilla y frecuente de almacenamiento de datos. Ya has aprendido a utilizar NumPy y Pandas: aprenderás a utilizar estos paquetes para importar archivos planos y personalizar tus importaciones.

Archivos planos#

Los archivos de texto plano se pueden clasificar en dos grandes tipos:

  1. Archivos que contienen texto sin formato . Por ejemplo:

no estructurado

  1. Archivos que contienen registros estructurados. Un ejemplo es el conjunto de datos del Titanic

estructurado

En este archivo, cada columna representa una característica o rasgo, como el género, la cabina o si la persona sobrevivió, mientras que cada fila corresponde a una persona que estaba a bordo del Titanic.

Es fundamental que cualquier científico de datos comprenda el concepto de archivo plano. Estos son archivos de texto simples que contienen datos organizados en tablas, pero sin relaciones estructuradas complejas.

Es probable que hayas notado que la extensión del archivo es .csv. Tal vez te preguntes qué significa:

  • .csv (Comma-Separated Values): Archivo en el que los valores están separados por comas.

  • .txt: Archivo de texto simple.

  • .tsv (Tab-Separated Values): Archivo en el que los valores están separados por tabulaciones.

Los valores en archivos planos pueden estar separados por diferentes caracteres, como comas o tabulaciones, conocidos como delimitadores. Estos delimitadores permiten organizar y estructurar los datos de manera sencilla y efectiva.

Ahora, para consultar cualquier archivo de texto sin formato, que debemos hacer:

  • Asignar el nombre del archivo a una variable como una cadena.

  • Usamos la función básica open de Python para abrir una conexión al archivo y le pasamos el argumento mode='r', lo que garantiza que solo podamos leerlo.

  • Despues le asignamos el texto del archivo a una variable text aplicando el método read a la conexión al archivo.

  • Después asegúrese de cerrar la conexión al archivo usando el comando file.close.

Miremos un ejemplo:

# Ejemplo

Puedes evitar tener que cerrar la conexión al archivo utilizando una declaración with. Esto le permite crear un contexto en el que puede ejecutar comandos con el archivo abierto. Una vez fuera de esta cláusula o contexto, el archivo ya no está abierto y, por esta razón, with se denomina administrador de contexto. Realmente asegura que el archivo se cierre correctamente, incluso si ocurre un error durante la escritura. Por ejemplo:

# Ejemplo

Ejercicios

  1. Abre el archivo de texto GabrielGarciaMarquez.txt e imprimelo. Utiliza el administrador de contexto with.

  2. En el caso de archivos grandes, puede que no queramos imprimir todo su contenido en el shell: tal vez quieras imprimir sólo las primeras líneas. Use el archivo de texto GabrielGarciaMarquez.txt e imprima las 3 primeras líneas. Sugerencia: use el método readline().

Importación y exportación de archivos planos con Numpy#

Ahora que sabes cómo usar la función incorporada open de Python para abrir archivos de texto, veamos cómo importar un archivo plano y asignarlo a una variable. Si todos los datos son numéricos, puedes usar el paquete NumPy para importarlos como una matriz NumPy. ¿Por qué querríamos hacer esto?

Características de las matrices NumPy

  1. Eficiencia y velocidad:

    • Las matrices NumPy son el estándar de Python para almacenar datos numéricos debido a su eficiencia y rapidez.

    • Son ideales para manejar grandes volúmenes de datos de manera limpia y ordenada.

    _images/NumPy.png
  2. Compatibilidad con otros paquetes:

    • NumPy es esencial para muchos otros paquetes en Python, como scikit-learn, un popular paquete de aprendizaje automático.

    _images/scikitlearn.png
    • Al trabajar con scikit-learn, es común que los datos estén en formato de matriz NumPy.

NumPy tiene varias funciones integradas que nos permiten importar datos como matrices de forma mucho más sencilla y eficiente. Aquí se encuentran las funciones loadtxt y genfromtxt.

  1. loadtxt: Importa datos de un archivo de texto como una matriz NumPy. Por ejemplo

# dataset
# mnist es una colección de dígitos manuscritos del 0 al 9

# Ejemplo

Algunos argumentos adicionales de loadtxt

  • skiprows: Si deseas omitir la primera fila (por ejemplo, un encabezado), puedes usar skiprows=1.

# Ejemplo
  • usecols: Si solo quieres importar columnas específicas, usa usecols con una lista de los índices de las columnas.

# Ejemplo
  • dtype: Te ayuda a importar diferentes tipos de datos en matrices. dtype=str garantiza que todas las entradas se importen como cadenas

# Ejemplo
  1. genfromtxt: Similar a loadtxt, pero más flexible para manejar datos mixtos. Además, cuando usamos dtype=None permite que NumPy adivine el tipo de datos para cada columna. Por ejemplo:

# Ejemplo

Ejercicios

Del archivo digitos.txt, que tiene la primera fila con los nombres de las variables y está delimitado por tabulaciones. Importe solo las 3 primeras columnas del archivo plano. Imprime la primera fila

Ahora, para exportar archivos planos usando NumPy, puedes utilizar la función numpy.savetxt(). Esta función es muy útil para guardar datos en un archivo de texto con un formato específico. Aquí te muestro un ejemplo básico:

# Crear una matriz NumPy
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# Ejemplo

Una breve explicación de los parámetros es la siguiente:

  • 'archivo.txt': Nombre del archivo en el que se guardarán los datos.

  • data: La matriz NumPy que deseas guardar.

  • fmt='%d': El formato en el que los datos se guardarán (en este caso, enteros). Puedes ajustar el formato según el tipo de datos que estás manejando (por ejemplo, %.2f para números de punto flotante con dos decimales).

  • delimiter=',': El delimitador que separa los valores en el archivo. Aquí se usa una coma, pero puedes cambiarlo a otro carácter como un espacio ' ' o un punto y coma ';'.

Si quieres agregar un encabezado al archivo, puedes hacerlo con el parámetro header:

# Ejemplo

Importación y exportación de archivos planos con Pandas#

En la ciencia de datos, se requiere manejar estructuras de datos etiquetadas bidimensionales con columnas de tipos potencialmente diferentes, algo que las matrices NumPy no pueden satisfacer completamente. Esta necesidad impulsó a Wes McKinney a desarrollar la biblioteca Pandas para Python, que se ha convertido en una herramienta esencial para los científicos de datos.

Pandas es una biblioteca de Python que permite llevar a cabo todo el flujo de trabajo de análisis de datos sin cambiar a otro lenguaje específico como R. La estructura de datos más relevante en Pandas es el DataFrame, que es el análogo Pythonic del marco de datos en R.

Características claves de Pandas

  • Importación de datos: Pandas facilita la importación de archivos planos, bases de datos, archivos Excel, entre otros, como DataFrames.

  • Estructuras de datos etiquetadas: Los DataFrames permiten manipular y analizar datos con etiquetas en filas y columnas, lo que facilita el manejo de diferentes tipos de datos en un solo lugar.

  • Manipulación de datos: Pandas ofrece funciones para cortar, remodelar, agrupar, unir y fusionar datos de manera eficiente.

  • Estadísticas y manejo de valores faltantes: Realiza cálculos estadísticos sin afectar los valores faltantes y proporciona herramientas para manejar series temporales.

Ahora importemos un archivo plano con Pandas:

# Importar un archivo CSV como DataFrame

# Ejemplo

También podemos convertir fácilmente el DataFrame en una matriz numpy.

# Ejemplo

Ejercicios

  1. Importe el dataset del titanic.csv, guardelo en el objeto df y muestre las 5 ultimas filas.

  2. Completa el código:

# Asignar el nombre de archivo: file
file = 'digitos.csv'

# Leer las primeras 5 filas del archivo en un DataFrame: data
# Use nrow y header
# TU CODIGO

# Construir un de numpy a partir del DataFrame: data_array
# TU CODIGO

# Imprimir el tipo de dato de data_array en la consola
print(type(data_array))
  1. Complete el código:

# Asignar el nombre del archivo: file
file = 'titanic_corrupt.txt'

# Importar el archivo: data
data = pd.read_csv(file, sep=____, comment=____, na_values=____)

# Imprimir las primeras filas del DataFrame
print(data.head())

donde

  • sep= es el delimitador que separa los campos en el archivo (en tu caso, debería ser '\t' o ',').

  • comment= especifica el carácter que indica el inicio de un comentario (en tu caso, debería ser '#' ).

  • na_values= define los valores que deben ser interpretados como valores faltantes (puedes usar `’NA’, 0 ‘NaN’ o ‘Nothing’).

Ahora, para exportar archivos planos usando pandas, puedes utilizar la función to_csv() para guardar datos en formato CSV. Aquí te muestro cómo hacerlo para archivos CSV y otros formatos comunes:

# Crear un DataFrame
data = {
    'Columna1': [1, 4, 7],
    'Columna2': [2, 5, 8],
    'Columna3': [3, 6, 9]
}
df = pd.DataFrame(data)

# Guardar el DataFrame en un archivo CSV

# Ejemplo

Una breve explicación de los parámetros de to_csv():

  • 'archivo.csv': Nombre del archivo CSV a generar.

  • index=False: Evita que se guarde la columna de índices del DataFrame en el archivo CSV.

Puedes usar to_csv() con diferentes delimitadores para crear archivos de texto con otros formatos:

# Ejemplo

Importación e exportación de datos de otros tipos de archivos#

Como científico de datos, es crucial saber cómo importar datos desde una variedad de tipos de archivo. En esta sección, exploraremos cómo importar datos en Python desde varios formatos importantes. Cubriremos:

  • Archivos serializados (Pickle): Usados para almacenar datos de manera eficiente en Python. El concepto de serializados (Pickle) un archivo está motivado por lo siguiente: si bien puede ser fácil guardar una matriz numpy o un dataframe de pandas en un archivo plano, hay muchos otros tipos de datos, como diccionarios y listas, para los cuales no es obvio cómo almacenarlos.

  • Hojas de Cálculo Excel: Permiten integrar datos de análisis de hojas de cálculo comunes.

  • Archivos SAS y Stata: Formatoss utilizados en software de estadística y análisis de datos.

Aprenderás a manejar estos formatos para que puedas trabajar con una amplia gama de datos en tus proyectos de ciencia de datos.

Importación y exportación de datos serializados#

Los datos serializados es el proceso de convertir los datos que han sido convertidos de su formato original (por ejemplo, un diccionario, una lista, un objeto de clase, etc.) a una secuencia de bytes. Este proceso se llama serialización o marshalling. La serialización permite que estos datos se almacenen en un archivo, se envíen a través de una red o se transmitan entre diferentes partes de un programa de manera eficiente. En Python, la serialización es manejada por el módulo pickle.

Por ejemplo

# Ejemplo

Ahora, exportemos los datos a un archivo .pkl usando pickle en Python, que es útil para serializar objetos de Python (como listas, diccionarios, o DataFrames). Aquí te muestro cómo hacerlo:

# Crear un objeto (por ejemplo, un diccionario)
data = {'a': 1, 'b': 2, 'c': 3}

# Guardar el objeto en un archivo pickle
# Ejemplo

Consideraciones

1 No cargues archivos pickle de fuentes no confiables, ya que pueden ejecutar código malicioso durante la deserialización.

  1. Archivos pickle son específicos de Python, por lo que no se pueden leer fácilmente en otros lenguajes de programación sin soporte para pickle.

Ejercicios

  1. Complete el código:

# Importar el paquete pickle 
# TU CÓDIGO

# Abre el archivo pickle y carga los datos llamados data: d
# TU CÓDIGO

# Imprime y el tipo de dato de d
# TU CÓDIGO

Importación y exportación de datos en Excel#

Las hojas de cálculo de Excel son una herramienta universalmente conocida y ampliamente utilizada, especialmente en el ámbito del análisis de datos. Un archivo de Excel generalmente contiene múltiples hojas de cálculo, cada una de las cuales puede almacenar diferentes conjuntos de datos relacionados o independientes. En el contexto de la ciencia de datos, el manejo eficiente de estos archivos es fundamental, y la biblioteca pandas de Python se destaca como una herramienta poderosa para este propósito.

Pandas permite importar archivos de Excel de manera sencilla y convertir sus hojas de cálculo en DataFrames, que son estructuras de datos optimizadas para el análisis y la manipulación de datos. La conversión de las hojas de Excel a DataFrames facilita enormemente el trabajo con los datos, ya que pandas proporciona una amplia gama de funciones para exploración, transformación y análisis.

Para comenzar, se puede utilizar la función ExcelFile de pandas para cargar un archivo de Excel en una variable, generalmente llamada data o algún nombre descriptivo. Este objeto ExcelFile actúa como un contenedor del archivo de Excel, permitiendo el acceso a sus diferentes hojas sin necesidad de cargarlas todas en la memoria al mismo tiempo.

# Ejemplo

Esto indica que el archivo contiene tres hojas de cálculo, cada una correspondiente a un rango de años diferente.

Una vez que conoces los nombres de las hojas, puedes cargar cualquier hoja en particular como un DataFrame para empezar a analizar los datos. Para hacer esto, utilizas el método parse del objeto ExcelFile. Este método acepta un argumento, que puede ser el nombre de la hoja como una cadena o su índice como un número entero (no como un float, ya que Python no acepta índices de hojas en forma de floats).

# Ejemplo

pandas es lo suficientemente inteligente para interpretar si le estás proporcionando un nombre de hoja o un índice, por lo que puedes utilizar cualquiera de los dos métodos según tu preferencia.

El método read_excel() de pandas es una función muy útil y versátil para leer archivos de Excel directamente en un DataFrame. A diferencia de ExcelFile y parse(), que se usan en conjunto cuando necesitas trabajar con múltiples hojas de un archivo de Excel, read_excel() es una función de uso directo que simplifica la lectura de una o más hojas de cálculo.

Algunos ejemplos del uso de la función read_excel()

  1. Leer una sola hoja de cálculo: Si sabes el nombre de la hoja que necesitas, puedes leerla directamente en un DataFrame:

# Lee la hoja '1960–1966' del archivo Excel y la carga en un DataFrame
# Ejemplo

O si prefieres usar el índice de la hoja:

# Ejemplo
  1. Leer múltiples hojas al mismo tiempo: Si necesitas cargar varias hojas de un archivo de Excel, read_excel() puede hacerlo en una sola llamada y devolver un diccionario donde las llaves son los nombres de las hojas y los valores son los DataFrames correspondientes.

# Ejemplo
  1. Leer todas las hojas de un archivo de Excel: Si quieres leer todas las hojas del archivo de Excel sin tener que especificar sus nombres, puedes hacerlo pasando None al argumento sheet_name.

# Lee todas las hojas del archivo Excel
# Ejemplo

read_excel() es ideal para situaciones en las que necesitas una solución rápida y directa para leer archivos de Excel en Python. Su simplicidad lo hace la primera opción para la mayoría de los casos de uso, mientras que ExcelFile y parse() ofrecen más flexibilidad para tareas más complejas.

Ahora, para exportar datos a un archivo Excel usando pandas, puedes utilizar el método to_excel() del DataFrame. Aquí te muestro cómo hacerlo, con opciones para personalizar la exportación. Por ejemplo

# Crear un DataFrame
data = {
    'Columna1': [1, 4, 7],
    'Columna2': [2, 5, 8],
    'Columna3': [3, 6, 9]
}
df = pd.DataFrame(data)

# Guardar el DataFrame en un archivo Excel
# Ejemplo

Si quieres exportar a múltiples hojas de un archivo excel, puedes guardar diferentes DataFrames en diferentes hojas del mismo archivo Excel usando un ExcelWriter:

with pd.ExcelWriter('_data/datamanip/archivo_multihojas.xlsx') as writer:
    df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
    df2 = pd.DataFrame({'X': [5, 6], 'Y': [7, 8]})
    
    # Guardar DataFrames en hojas diferentes
    df1.to_excel(writer, sheet_name='Hoja1', index=False)
    df2.to_excel(writer, sheet_name='Hoja2', index=False)

Ejercicios

  1. Complete el código:

# Asigna el nombre del archivo de excel battledeath: file
# TU CÓDIGO

# Cargar hoja de cálculo: xls
# TU CÓDIGO

# Imprimir nombres de hojas
# TU CÓDIGO
  1. Usando el punto anterior: Complete

# Cargar una hoja en un DataFrame por nombre: df1
df1 = xls.parse(__TU CÓDIGO__)

# Imprimir las primeras filas del DataFrame df1
print(__TU CÓDIGO__)

# Cargar una hoja en un DataFrame por índice: df2
df2 = xls.parse(__TU CÓDIGO__)

# Imprimir las primeras filas del DataFrame df2
print(__TU CÓDIGO__)
  1. Usando el punto anterior. Complete en código en python. Sugerencia: Los valores pasados a skiprows y names deben ser todos del tipo list

# Analizar la primera hoja y renombrar las columnas: df1
df1 = xls.parse(__TU CÓDIGO__, skiprows=__TU CÓDIGO__, names=__TU CÓDIGO__)

# Imprimir las primeras filas del DataFrame df1
print(df1.head())

# Analizar la primera columna de la segunda hoja y renombrar la columna: df2
df2 = xls.parse(__TU CÓDIGO__, usecols=__TU CÓDIGO__, skiprows=__TU CÓDIGO__, names=__TU CÓDIGO__)

# Imprimir las primeras filas del DataFrame df2
print(df2.head())

Importación de ficheros planos desde la web#

Ahora puedes importar datos en Python desde todo tipo de archivos planos como .txt, .csv, otros tipos de archivos como archivos pickled, hojas de cálculo de Excel y archivos SAS y Stata. También has adquirido una valiosa experiencia en la consulta de bases de datos relacionales para importar datos de ellas mediante SQL. Sin embargo, todas estas habilidades implican la importación de datos de archivos que tiene localmente. Sin embargo, estas habilidades usualmente implican trabajar con archivos locales. En muchos casos, como científico de datos, necesitarás importar datos directamente desde la web.

Por ejemplo, supongamos que necesitas obtener el conjunto de datos de unas campañas de marketing directo (llamadas telefónicas) de una institución bancaria portuguesa desde el repositorio de GitHub de cdeoroaguado. Aunque puedes hacerlo manualmente usando un navegador, este método no es reproducible ni escalable. Es más eficiente y profesional utilizar código Python para automatizar la descarga e importación de estos datos.

Para hacer el proceso de importación desde la Web debemos tener algunos conceptos claros.

El paquete urllib en Python proporciona una interfaz de alto nivel para obtener datos de la World Wide Web. En particular, la función urlopen es similar a la función integrada open, pero acepta URLs en lugar de nombres de archivo.

Características de urllib

urllib tiene algunas funciones inmersas. Algunas son:

  • urlopen: Abre una URL y devuelve un objeto similar a un archivo.

  • urlretrieve: Descarga archivos directamente desde una URL y los guarda localmente.

Observación

  • Es útil para tareas sencillas de importación de datos desde la web.

  • Para tareas más complejas, podrías considerar el uso de requests junto con BeautifulSoup.

# Ejemplo

Tambíen, podias hacer la lectura de los datos, sin descargalos. Por ejemplo

# Ejemplo

Manipulación de datos con pandas#

La librería pandas (cuyo nombre deriva de panel data, un término utilizado para describir conjuntos de datos estructurados y multidimensionales) ofrece potentes estructuras de datos y funciones de alto nivel que facilitan el trabajo con datos estructurados de manera eficiente y cómoda. Es una herramienta esencial en el análisis de datos, ampliamente utilizada por su versatilidad y funcionalidad.

_images/pandas.png

Entre los principales objetos que proporciona pandas se encuentran el DataFrame, una estructura tabular bidimensional, la Serie, ambos construidos sobre arrays multidimensionales de NumPy y el Panel, que representa un cubo de datos tridimensional. Aunque NumPy es excelente para el almacenamiento eficiente de datos con su estructura `ndarray, presenta ciertas limitaciones en análisis más complejos. Estas limitaciones incluyen la falta de flexibilidad para aplicar etiquetas a los datos, gestionar valores faltantes, realizar agrupaciones, entre otros. Pandas supera estas barreras con sus estructuras de datos avanzadas, proporcionando una mayor flexibilidad y funcionalidad.

Para más información, puedes consultar la documentación oficial de pandas, donde encontrarás recursos y ejemplos detallados para aprovechar al máximo esta poderosa librería.

Recordemos algunas cosas de pandas

Para iniciar el proceso de creación, manipulación, entre otras debemos instalar el ia en el terminal. Recuerde activar el ambiente.

installpandas

Importemos la libreria numpy y pandas

import pandas as pd
import numpy as np

Ahora, daremos los conceptos y ejemplos de una series.

Series#

Las series son estructuras similares a los arrays unidimensionales que ya hemos visto, con la diferencia de que también son homogéneas. Esto significa que todos sus elementos deben ser del mismo tipo y que su tamaño es fijo, es decir, no se puede modificar una vez definido.

Vamos a comenzar creando una serie a partir de una lista. Primero, necesitamos definir una lista con algunos datos. Por ejemplo:

# Definimos una lista de trabajos
trabajos = ["Ingeniero de Software", "Analista de Datos",
            "Diseñador UX", "Gerente de Producto",
            "Científico de datos"]

# Creamos un índice personalizado para estos trabajos
indices = ["Empresa1", "Empresa2", "Empresa3", 
           "Empresa4","Empresa5"]

Para crear la serie en Pandas usando estos datos y con indices personalizados, utilizamos el siguiente código:

serie = pd.Series(data = trabajos,dtype='string')
print(serie)

serie = pd.Series(data = trabajos,index=indices, dtype='string')
print(serie)
0    Ingeniero de Software
1        Analista de Datos
2             Diseñador UX
3      Gerente de Producto
4      Científico de datos
dtype: string
Empresa1    Ingeniero de Software
Empresa2        Analista de Datos
Empresa3             Diseñador UX
Empresa4      Gerente de Producto
Empresa5      Científico de datos
dtype: string

Ahora, vamos a crear una serie a partir de un diccionario

# Definimos un diccionario con trabajos y sus respectivos salarios
diccionario = {
    "Ingeniero de Software": 70000,
    "Analista de Datos": 60000,
    "Diseñador UX": 65000,
    "Gerente de Producto": 80000,
    "Científico de datos": 65000
}

# Creamos una serie a partir del diccionario
serie_diccionario = pd.Series(diccionario)
print(serie_diccionario)
Ingeniero de Software    70000
Analista de Datos        60000
Diseñador UX             65000
Gerente de Producto      80000
Científico de datos      65000
dtype: int64

Para explorar algunos atributos de la serie, puedes usar los siguientes métodos:

# Tamaño de nuestra serie
serie_diccionario.size

# imprimir la lista de los nombres de las filas
serie_diccionario.index

# imprimir el tipo de datos
serie_diccionario.dtype
dtype('int64')

Para acceder a los elementos de la serie

# Accedemos a un elemento específico usando su índice
serie_diccionario['Ingeniero de Software']

# Accedemos a un rango de valores
serie_diccionario[0:3]

# Accedemos a múltiples elementos usando una lista de índices
serie_diccionario[['Ingeniero de Software','Analista de Datos']]
Ingeniero de Software    70000
Analista de Datos        60000
dtype: int64
serie_diccionario['Profesor'] = 100000
serie_diccionario
Ingeniero de Software     70000
Analista de Datos         60000
Diseñador UX              65000
Gerente de Producto       80000
Científico de datos       65000
Profesor                 100000
dtype: int64

También puedes utilizar algunos métodos útiles para análisis, como:

# Usamos métodos para obtener estadísticas de la serie
print(serie_diccionario.count())
print(serie_diccionario.sum())
print(serie_diccionario.cumsum())
print(serie_diccionario.value_counts())
print(serie_diccionario.min())
print(serie_diccionario.max())
print(serie_diccionario.mean())
print(serie_diccionario.std())
print(serie_diccionario.quantile(0.25))
print(serie_diccionario.quantile(0.5))
print(serie_diccionario.quantile(0.75))
print(serie_diccionario.describe())
6
440000
Ingeniero de Software     70000
Analista de Datos        130000
Diseñador UX             195000
Gerente de Producto      275000
Científico de datos      340000
Profesor                 440000
dtype: int64
65000     2
70000     1
60000     1
80000     1
100000    1
Name: count, dtype: int64
60000
100000
73333.33333333333
14719.601443879745
65000.0
67500.0
77500.0
count         6.000000
mean      73333.333333
std       14719.601444
min       60000.000000
25%       65000.000000
50%       67500.000000
75%       77500.000000
max      100000.000000
dtype: float64

Exploraremos cómo aplicar operaciones matemáticas y funciones a series de datos relacionadas con bancos, así como buscar información mediante condiciones, ordenar series y eliminar datos nulos o desconocidos.

  1. Operaciones Matemáticas Básicas

Primero, veremos cómo aplicar operaciones matemáticas a una serie que representa los saldos de las cuentas bancarias. A continuación, presentamos algunos ejemplos prácticos:

# Una serie con saldos de cuentas bancarias

saldos = pd.Series([1500, 2000, 2500, 3000, 3500])

# Ejemplo
  1. Filtrado de Datos

El objetivo es seleccionar saldos que cumplan una condición. Por ejemplo

# Seleccionar saldos mayores o iguales a 3000
# Ejemplo

# Seleccionar saldos diferentes a 3000
# Ejemplo
  1. Ordenar series

Para ordenar los saldos de manera ascendente o descendente:

# Ejemplo
  1. Eliminación de Datos Nulos y Desconocidos

Finalmente, para eliminar datos nulos o desconocidos en la serie de saldos:

# Crear valores nulos en la serie de saldos
saldos = pd.Series([1500, np.nan, 2500, None, 3500])

# Eliminar valores nulos
saldos_limpios = saldos.dropna()

print(saldos_limpios)
0    1500.0
2    2500.0
4    3500.0
dtype: float64

Con estos ejemplos, has aprendido cómo realizar diversas operaciones con series relacionadas con datos bancarios en Pandas. En la próximo sección, exploraremos cómo trabajar con DataFrames.

Pandas#

En este módulo, profundizaremos en la creación de DataFrames, una de las estructuras de datos más versátiles y poderosas para la manipulación de información financiera. Exploraremos tres métodos distintos para construir DataFrames, cada uno con aplicaciones específicas en la industria bancaria.

Un DataFrame es una estructura bidimensional, similar a una tabla, que nos permite organizar y manipular datos con facilidad. En el contexto bancario, los DataFrames son ideales para manejar información de clientes, transacciones, productos financieros, y otros tipos de datos críticos.

Método 1: Creación de DataFrames a partir de Diccionarios#

En este primer enfoque, utilizaremos un diccionario para organizar los datos de clientes bancarios. Las claves del diccionario representarán las columnas del DataFrame, tales como Nombre, Edad, Saldo, y Calificación_Crédito.

# Importación de la librería pandas
import pandas as pd

# Definición de los datos mediante un diccionario
clientes = {
    'Nombre': ['José', 'Rodolfo', 'María', 'Julieta'],
    'Edad': [45, 52, 34, 29],
    'Saldo': [50000, 70000, 60000, 15000],
    'Calificación_Crédito': [700, 750, 680, 720]
}

# Creación del DataFrame utilizando el diccionario
df_clientes = pd.DataFrame(clientes)

# Visualización del DataFrame
print(df_clientes)

Este enfoque es eficiente cuando se tiene un conjunto de datos bien estructurado, con columnas predefinidas y valores coherentes. Es comúnmente utilizado en situaciones donde los datos provienen de sistemas bancarios estructurados, como bases de datos relacionales.

Método 2: Creación de DataFrames a partir de Listas Anidadas#

El siguiente método consiste en utilizar listas de listas para estructurar los datos. Este enfoque puede ser útil cuando los datos provienen de una fuente menos estructurada, como archivos CSV o entrada manual.

# Definición de los datos mediante listas anidadas
datos_clientes = [
    ['José', 45, 50000, 700],
    ['Rodolfo', 52, 70000, 750],
    ['María', 34, 60000, 680],
    ['Julieta', 29, 15000, 720]
]

# Definición de las columnas
columnas = ['Nombre', 'Edad', 'Saldo', 'Calificación_Crédito']

# Creación del DataFrame
df_clientes_lista = pd.DataFrame(datos_clientes, columns=columnas)

# Visualización del DataFrame
print(df_clientes_lista)

Este método es particularmente útil cuando los datos no están previamente etiquetados y requieren un procesamiento adicional para ser organizados en un formato tabular. Es frecuente en la integración de datos desde múltiples fuentes no homogéneas, como encuestas o registros de transacciones.

Método 3: Creación de DataFrames a partir de Listas de Diccionarios#

Finalmente, exploraremos cómo crear un DataFrame a partir de una lista de diccionarios. Este método es flexible y permite manejar datos con campos opcionales o información incompleta, algo común en grandes bases de datos bancarias.

# Definición de los datos mediante una lista de diccionarios
clientes_dict = [
    {'Nombre': 'José', 'Edad': 45, 'Saldo': 50000, 'Calificación_Crédito': 700},
    {'Nombre': 'Rodolfo', 'Edad': 52, 'Saldo': 70000, 'Calificación_Crédito': 750},
    {'Nombre': 'María', 'Edad': 34, 'Saldo': 60000},  # Falta calificación de crédito
    {'Nombre': 'Julieta', 'Edad': 29, 'Calificación_Crédito': 720},  # Falta saldo
    {'Edad': 28, 'Saldo': 30000}  # Faltan nombre y calificación de crédito
]

# Creación del DataFrame
df_clientes_dict = pd.DataFrame(clientes_dict)

# Visualización del DataFrame
print(df_clientes_dict)

La capacidad de manejar datos incompletos o parcialmente definidos es crucial en el análisis de datos bancarios, donde la información puede provenir de fuentes dispares y no siempre estará completa. Este método permite construir DataFrames robustos que pueden ser limpiados o completados en etapas posteriores del análisis.

Observación

Algunas diferencias clave entre una Serie (Series) y un DataFrame en Pandas:

  1. Dimensionalidad:

    • Serie: Es unidimensional, como una lista o columna única de datos.

    • DataFrame: Es bidimensional, similar a una tabla con múltiples filas y columnas.

  2. Estructura:

    • Serie: Contiene una sola columna de datos con un índice.

    • DataFrame: Contiene múltiples columnas, cada una de las cuales es una Serie.

  3. Uso:

    • Serie: Ideal para manejar una sola secuencia de datos.

    • DataFrame: Ideal para trabajar con datos tabulares que tienen múltiples variables o características.

  4. Etiquetas del Eje:

    • Serie: Tiene un único conjunto de etiquetas o índice asociado con los datos.

    • DataFrame: Tiene dos ejes de etiquetas: uno para las filas (índice) y otro para las columnas.

  5. Operaciones de Agregación:

    • Serie: Las operaciones de agregación, como la suma o el promedio, se aplican directamente a la secuencia de datos.

    • DataFrame: Puedes aplicar operaciones de agregación a lo largo de filas o columnas, permitiendo un análisis más detallado y comparativo.

Manipulación#

La manipulación de datos con Pandas es una de las habilidades fundamentales en el análisis de datos. Pandas es una biblioteca de Python que proporciona estructuras de datos fáciles de usar, como Series y DataFrames, que permiten realizar operaciones y transformaciones complejas de manera sencilla y eficiente.

Introducción a la manipulación de datos#

Ahora carguemos el conjunto de datos de marketing del banco bank-full.

Los datos están relacionados con campañas de marketing directo (llamadas telefónicas) de una institución bancaria portuguesa.

Este conjunto de datos tiene 4521 observaciones y 17 variables. Las variables son:

  • age: Edad del cliente.

  • job: Profesión del cliente (por ejemplo, desempleado, servicios, gestión).

  • marital: Estado civil del cliente (soltero, casado, divorciado).

  • education: Nivel educativo del cliente (primaria, secundaria, terciaria).

  • default : Indica si el cliente tiene crédito en incumplimiento (sí o no).

  • balance: Saldo promedio anual de la cuenta bancaria del cliente.

  • housing: Indica si el cliente tiene un préstamo hipotecario (sí o no).

  • loan: Indica si el cliente tiene un préstamo personal (sí o no).

  • contact: Tipo de comunicación de contacto (teléfono celular, teléfono fijo).

  • day: Día del mes en que se realizó el último contacto con el cliente.

  • month: Mes en que se realizó el último contacto con el cliente.

  • duration: Duración del último contacto en segundos.

  • campaign: Número de contactos realizados durante esta campaña de marketing.

  • pdays: Días que han pasado desde que el cliente fue contactado por última vez en una campaña anterior (valores -1 indican que el cliente no fue contactado previamente).

  • previous: Número de contactos realizados antes de esta campaña.

  • poutcome: Resultado de una campaña de marketing anterior (éxito, fracaso, desconocido).

  • y: Resultado de la campaña actual (si el cliente suscribió o no un depósito a plazo fijo).

import pandas as pd
filename = 'C:/GitHub/Datos/datamanip/bank/bank-full.csv'
data = pd.read_csv(filename,sep=';')

data.head()
age job marital education default balance housing loan contact day month duration campaign pdays previous poutcome y
0 58 management married tertiary no 2143 yes no unknown 5 may 261 1 -1 0 unknown no
1 44 technician single secondary no 29 yes no unknown 5 may 151 1 -1 0 unknown no
2 33 entrepreneur married secondary no 2 yes yes unknown 5 may 76 1 -1 0 unknown no
3 47 blue-collar married unknown no 1506 yes no unknown 5 may 92 1 -1 0 unknown no
4 33 unknown single unknown no 1 no no unknown 5 may 198 1 -1 0 unknown no
url = 'https://raw.githubusercontent.com/cdeoroaguado/Datos/refs/heads/main/datamanip/bank/bank-full.csv'

df = pd.read_csv(url,sep=';')

df.head()
age job marital education default balance housing loan contact day month duration campaign pdays previous poutcome y
0 58 management married tertiary no 2143 yes no unknown 5 may 261 1 -1 0 unknown no
1 44 technician single secondary no 29 yes no unknown 5 may 151 1 -1 0 unknown no
2 33 entrepreneur married secondary no 2 yes yes unknown 5 may 76 1 -1 0 unknown no
3 47 blue-collar married unknown no 1506 yes no unknown 5 may 92 1 -1 0 unknown no
4 33 unknown single unknown no 1 no no unknown 5 may 198 1 -1 0 unknown no
df. tail()

# concatenar
result = pd.concat([df.head(),df.tail()],ignore_index=True)
result
age job marital education default balance housing loan contact day month duration campaign pdays previous poutcome y
0 58 management married tertiary no 2143 yes no unknown 5 may 261 1 -1 0 unknown no
1 44 technician single secondary no 29 yes no unknown 5 may 151 1 -1 0 unknown no
2 33 entrepreneur married secondary no 2 yes yes unknown 5 may 76 1 -1 0 unknown no
3 47 blue-collar married unknown no 1506 yes no unknown 5 may 92 1 -1 0 unknown no
4 33 unknown single unknown no 1 no no unknown 5 may 198 1 -1 0 unknown no
5 51 technician married tertiary no 825 no no cellular 17 nov 977 3 -1 0 unknown yes
6 71 retired divorced primary no 1729 no no cellular 17 nov 456 2 -1 0 unknown yes
7 72 retired married secondary no 5715 no no cellular 17 nov 1127 5 184 3 success yes
8 57 blue-collar married secondary no 668 no no telephone 17 nov 508 4 -1 0 unknown no
9 37 entrepreneur married secondary no 2971 no no cellular 17 nov 361 2 188 11 other no

Las dimensiones del dataset:

df.shape
(45211, 17)

Información de la estructura del dataset de marketing:

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 45211 entries, 0 to 45210
Data columns (total 17 columns):
 #   Column     Non-Null Count  Dtype 
---  ------     --------------  ----- 
 0   age        45211 non-null  int64 
 1   job        45211 non-null  object
 2   marital    45211 non-null  object
 3   education  45211 non-null  object
 4   default    45211 non-null  object
 5   balance    45211 non-null  int64 
 6   housing    45211 non-null  object
 7   loan       45211 non-null  object
 8   contact    45211 non-null  object
 9   day        45211 non-null  int64 
 10  month      45211 non-null  object
 11  duration   45211 non-null  int64 
 12  campaign   45211 non-null  int64 
 13  pdays      45211 non-null  int64 
 14  previous   45211 non-null  int64 
 15  poutcome   45211 non-null  object
 16  y          45211 non-null  object
dtypes: int64(7), object(10)
memory usage: 5.9+ MB

El atributo df.size en pandas devuelve el número total de elementos en un DataFrame. Esto se calcula multiplicando el número de filas por el número de columnas. Es útil para obtener una visión rápida del tamaño total del DataFrame en términos de elementos.

# número total de elementos en el dataframe
df.size
768587

Puede ocurrir que el conjunto de datos de marketing para la banca tenga duplicados. El método drop_duplicates() en pandas se utiliza para eliminar filas duplicadas de un DataFrame. Este método permite identificar y remover filas que contienen los mismos valores en las columnas seleccionadas, o en todas las columnas si no se especifica ninguna.

# Eliminar filas duplicadas
df = df.drop_duplicates()
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 45211 entries, 0 to 45210
Data columns (total 17 columns):
 #   Column     Non-Null Count  Dtype 
---  ------     --------------  ----- 
 0   age        45211 non-null  int64 
 1   job        45211 non-null  object
 2   marital    45211 non-null  object
 3   education  45211 non-null  object
 4   default    45211 non-null  object
 5   balance    45211 non-null  int64 
 6   housing    45211 non-null  object
 7   loan       45211 non-null  object
 8   contact    45211 non-null  object
 9   day        45211 non-null  int64 
 10  month      45211 non-null  object
 11  duration   45211 non-null  int64 
 12  campaign   45211 non-null  int64 
 13  pdays      45211 non-null  int64 
 14  previous   45211 non-null  int64 
 15  poutcome   45211 non-null  object
 16  y          45211 non-null  object
dtypes: int64(7), object(10)
memory usage: 5.9+ MB
df_sin_nulos = df.dropna()
df_sin_nulos.info()

Ahora, el nombres de las variables, el indice, el tipo de dato del dataset de marketing

# nombre de las variables
df.columns

# Obtener el índice del DataFrame
df.index

# tipo de dato
df.dtypes
age           int64
job          object
marital      object
education    object
default      object
balance       int64
housing      object
loan         object
contact      object
day           int64
month        object
duration      int64
campaign      int64
pdays         int64
previous      int64
poutcome     object
y            object
dtype: object

Queremos saber los clientes menores de 20 años:

# Seleccionar solo las filas donde la condición es True
# df['age'] < 20
df.loc[:,'age'] < 20

# Mostrar los clientes menores de 20 años
dfm20 = df[df.loc[:,'age'] < 20]

# imprimir el dataframe las 5 primeras
dfm20.head()
age job marital education default balance housing loan contact day month duration campaign pdays previous poutcome y
30791 19 student single unknown no 1169 no no cellular 6 feb 463 18 -1 0 unknown no
31041 19 student single unknown no 0 no no cellular 11 feb 123 3 -1 0 unknown no
31263 19 student single unknown no 27 no no telephone 5 mar 86 12 -1 0 unknown no
31304 19 student single secondary no 1803 no no cellular 10 mar 59 1 -1 0 unknown no
31432 19 student single primary no 134 no no cellular 27 mar 271 2 -1 0 unknown yes

Escojamos las columnas age, marital, balance, y de los clientes menores de 20

new_dfm20 = dfm20[['age','marital','balance','y']]
new_dfm20.head()
age marital balance y
30791 19 single 1169 no
31041 19 single 0 no
31263 19 single 27 no
31304 19 single 1803 no
31432 19 single 134 yes
new_dfm20.to_csv('C:/Users/cdeor/OneDrive/Escritorio/archivo.csv',sep = ';',index =False)

Para saber quien tiene mayor balance en la cuenta de los menores de 20, debo ordenarlo usando el método sort_values:

# ordenar
new_dfm20.sort_values(by='balance', ascending=False)
age marital balance y
34281 19 single 5368 no
40736 18 single 1944 no
40376 19 single 1803 no
31304 19 single 1803 no
33774 19 single 1247 no
30791 19 single 1169 no
31492 19 single 779 yes
32169 19 single 626 no
43680 19 single 608 yes
42274 18 single 608 yes
40887 18 single 608 yes
41446 19 single 527 no
42488 19 single 526 no
44058 19 single 526 no
44644 18 single 438 no
44042 19 single 424 no
43408 19 single 394 yes
44110 19 single 372 yes
43637 18 single 348 yes
41930 19 single 329 yes
43594 19 single 329 yes
44211 19 single 302 yes
34675 19 single 291 no
45170 19 single 245 no
41619 19 single 179 no
42146 18 single 156 no
31432 19 single 134 yes
44493 19 single 108 yes
40744 18 single 108 yes
41487 18 single 108 yes
42954 18 single 108 yes
43258 19 single 108 yes
42705 19 single 103 no
40564 19 single 103 yes
41830 19 single 103 no
33789 19 single 96 no
41500 19 single 88 no
41057 19 single 60 no
40927 19 single 56 no
41706 19 single 55 no
41222 18 single 35 no
31263 19 single 27 no
41252 18 single 5 no
41402 19 single 4 no
41273 18 single 3 yes
34288 19 single 0 no
31041 19 single 0 no

Puedes aplicar una función personalizada a una columna específica del DataFrame usando el método apply() de pandas. Supongamos que deseas crear una nueva columna llamada balance_category que clasifique el balance de cada cliente en "Bajo", "Medio" o "Alto" según ciertos umbrales.

def categorizar_balance(balance):
    if balance < 500:
        return 'Bajo'
    elif 500 <= balance < 1500:
        return 'Medio'
    else:
        return 'Alto'
# new_dfm20['balance_category'] = new_dfm20['balance'].apply(categorizar_balance)
new_dfm20.loc[:,'balance_category'] = new_dfm20['balance'].apply(categorizar_balance)
new_dfm20.head()
age marital balance y balance_category
30791 19 single 1169 no Medio
31041 19 single 0 no Bajo
31263 19 single 27 no Bajo
31304 19 single 1803 no Alto
31432 19 single 134 yes Bajo

Ahora, debemos obtener los clientes menores de 20 que si se suscribieron. Ademas los que se suscribieron con balance bajo.

# menores de 20 que se suscribieron
new_dfm20.loc[new_dfm20['y']=='yes']

# Otra forma de seleccionarlos
new_dfm20[new_dfm20['y'].isin(['yes'])]

# menores de 20 que se suscribieron con balance bajo
new_dfm20.loc[(new_dfm20['y']=='yes') & (new_dfm20['balance_category']=='Bajo')].head()
age marital balance y balance_category
31432 19 single 134 yes Bajo
40564 19 single 103 yes Bajo
40744 18 single 108 yes Bajo
41273 18 single 3 yes Bajo
41487 18 single 108 yes Bajo
Adición de nuevas columnas al DataFrame#

En este ejercicio, vamos a añadir nuevas columnas al conjunto de datos de diamantes en la biblioteca pandas. Empezaremos con la adición simple de columnas y luego avanzaremos y veremos la adición condicional de columnas. Para ello, vamos a seguir los siguientes pasos:

  • Anade una columna balance_por_age al DataFrame. Del mismo modo, también podemos utilizar la suma, la resta y otros operadores matemáticos sobre dos columnas numéricas.

# Ejemplo
  • Ahora, veremos la adición condicional de columnas. Vamos a intentar añadir una columna basada en el valor de la edad, digamos que todo lo que sea más de 17 como mayor de edad (codificado como 1) y todo lo que sea inferior a 17 como menor de edad (codificado como 0).

# Ejemplo

Descripción estadística#

Exploraremos cómo obtener estadísticas de resumen detalladas para columnas específicas de un DataFrame, así como cómo realizar análisis estadísticos avanzados mediante agrupaciones y tablas dinámicas. Comenzaremos con el cálculo de métricas descriptivas básicas, tales como medias, medianas, y desviaciones estándar, para evaluar la distribución y variabilidad de los datos. A continuación, abordaremos técnicas para aplicar estas estadísticas a subconjuntos de datos mediante agrupaciones, permitiendo un análisis más granular y enfocado.

Finalmente, dominaremos el uso de tablas dinámicas para sintetizar, visualizar y resumir datos complejos, facilitando la extracción de insights clave y patrones significativos en grandes volúmenes de información. Este enfoque integral fortalecerá tu capacidad para extraer, interpretar y comunicar hallazgos estadísticos de manera efectiva en el análisis de datos.

Resumen estadístico univariado#

Calculemos las medidas descriptivas fundamentales, incluyendo la media, mediana, moda, varianza, desviación estándar y cuartiles, para proporcionar una visión general de la distribución de los datos. Usaremos el conjunto de datos.

  1. Si la variable es numérica

df['age'].mean()

# Resumen descriptivo de una sola variable numérica
df['age'].agg({
    'Promedio':'mean',
    'Desv Estandar':'std',
    'Minimo':'min',
    'Maximo':'max',
    'Mediana':'median',
    'Q1': lambda x: x.quantile(0.25),
    'Q3': lambda x: x.quantile(0.75)
})
Promedio         40.936210
Desv Estandar    10.618762
Minimo           18.000000
Maximo           95.000000
Mediana          39.000000
Q1               33.000000
Q3               48.000000
Name: age, dtype: float64
result = pd.DataFrame({
    'Promedio':df[['age','balance']].mean(),
    'Desv. Estandar':df[['age','balance']].std(),
    'Minimo':df[['age','balance']].min(),
    'Maximo':df[['age','balance']].max(),
    'Mediana':df[['age','balance']].median(),
    'Q1':df[['age','balance']].quantile(0.25),
    'Q3':df[['age','balance']].quantile(0.75)
})

result
Promedio Desv. Estandar Minimo Maximo Mediana Q1 Q3
age 40.936210 10.618762 18 95 39.0 33.0 48.0
balance 1362.272058 3044.765829 -8019 102127 448.0 72.0 1428.0
  1. Si la variable es catégorica

conteo = df['job'].value_counts()
conteo

proporcion = df['job'].value_counts(normalize=True)
proporcion

porcentaje = df['job'].value_counts(normalize=True)*100
porcentaje

resultado = pd.DataFrame({
    'Numero de clientes':conteo,
    'Porcentaje':porcentaje
})

resultado
Numero de clientes Porcentaje
job
blue-collar 9732 21.525735
management 9458 20.919688
technician 7597 16.803433
admin. 5171 11.437482
services 4154 9.188029
retired 2264 5.007631
self-employed 1579 3.492513
entrepreneur 1487 3.289023
unemployed 1303 2.882042
housemaid 1240 2.742695
student 938 2.074716
unknown 288 0.637013
conteo = df[['job','education']].value_counts()
conteo

proporcion = df[['job','education']].value_counts(normalize=True)
proporcion

porcentaje = df[['job','education']].value_counts(normalize=True)*100
porcentaje

resultado = pd.DataFrame({
    'Numero de clientes':conteo,
    'Porcentaje':porcentaje
})

resultado
Numero de clientes Porcentaje
job education
management tertiary 7801 17.254650
blue-collar secondary 5371 11.879852
technician secondary 5229 11.565769
admin. secondary 4219 9.331800
blue-collar primary 3758 8.312136
services secondary 3457 7.646369
technician tertiary 1968 4.352923
management secondary 1121 2.479485
retired secondary 984 2.176461
self-employed tertiary 833 1.842472
retired primary 795 1.758422
unemployed secondary 728 1.610228
entrepreneur tertiary 686 1.517330
housemaid primary 627 1.386831
self-employed secondary 577 1.276238
admin. tertiary 572 1.265179
entrepreneur secondary 542 1.198823
student secondary 508 1.123620
blue-collar unknown 454 1.004180
housemaid secondary 395 0.873681
retired tertiary 366 0.809538
services primary 345 0.763089
management primary 294 0.650284
unemployed tertiary 289 0.639225
primary 257 0.568446
management unknown 242 0.535268
technician unknown 242 0.535268
student tertiary 223 0.493243
admin. primary 209 0.462277
services tertiary 202 0.446794
entrepreneur primary 183 0.404769
housemaid tertiary 173 0.382650
admin. unknown 171 0.378227
student unknown 163 0.360532
technician primary 158 0.349472
services unknown 150 0.331778
blue-collar tertiary 149 0.329566
self-employed primary 130 0.287541
unknown unknown 127 0.280905
retired unknown 119 0.263210
entrepreneur unknown 76 0.168101
unknown secondary 71 0.157041
primary 51 0.112804
housemaid unknown 45 0.099533
student primary 44 0.097321
self-employed unknown 39 0.086262
unknown tertiary 39 0.086262
unemployed unknown 29 0.064144
Resumen estadístico bivariado#

El resumen estadístico bivariado se refiere al estudio de dos variables simultáneamente para determinar si existe alguna relación o asociación entre ellas. Solo realizaremos las tablas para dicho análisis estadístico.

  1. Variable categórica vs variable numérica

df.groupby('y')['age'].mean()

var_num_cat = df.groupby('y')['age'].agg([
    ('Promedio','mean'),
    ('Desv. Estandar','std'),
    ('Minimo','min'),
    ('Maximo','max'),
    ('Mediana','median'),
    ('Q1',lambda x: x.quantile(0.25)),
    ('Q3',lambda x: x.quantile(0.75))
])

var_num_cat
Promedio Desv. Estandar Minimo Maximo Mediana Q1 Q3
y
no 40.838986 10.172662 18 95 39.0 33.0 48.0
yes 41.670070 13.497781 18 95 38.0 31.0 50.0
Resumen estadístico con tablas dinámicas#

Las tablas dinámicas son otras formas de calcular estadística de resumen agrupada. Por ejemplo

# Ejemplo

Ahora, usemos pivot_table para dos variables categóricas. Por ejemplo

# Ejemplo

Para crear una tabla de contigencia, basta con tener dos variables categóricas. Por ejemplo

# Ejemplo

Indices explicitos#

En Python, los índices son utilizados para acceder a elementos en estructuras de datos como listas, tuplas, y matrices (arrays). Un índice explícito se refiere a la práctica de definir de manera específica el índice que se va a utilizar para acceder a un elemento, en lugar de depender de la indexación automática por la posición.

Características de los Índices Explícitos

  • Flexibilidad: Permiten el acceso a elementos específicos de una estructura de datos sin necesidad de recorrer secuencialmente todos los elementos.

  • Claridad: Facilitan la lectura y comprensión del código al hacer evidente qué elementos se están accediendo o modificando.

  • Manipulación de Datos: Hacen más sencillo realizar operaciones como reordenar elementos, filtrar,seleccionar, agrupar o acceder a subconjuntos de datos.

  • Compatibilidad con Pandas: En bibliotecas como pandas, los índices explícitos son fundamentales para trabajar con Series y DataFrames, permitiendo indexar tanto por números como por etiquetas.

  • Precisión: Al especificar el índice, reduces el riesgo de errores al manipular datos.

  • Eficiencia: Mejoran la eficiencia al permitir operaciones directas sobre los elementos deseados.

Visualicemos nuevamente el dataframe de marketing para la banca.

# marco de datos
df.head()
age job marital education default balance housing loan contact day month duration campaign pdays previous poutcome y
0 58 management married tertiary no 2143 yes no unknown 5 may 261 1 -1 0 unknown no
1 44 technician single secondary no 29 yes no unknown 5 may 151 1 -1 0 unknown no
2 33 entrepreneur married secondary no 2 yes yes unknown 5 may 76 1 -1 0 unknown no
3 47 blue-collar married unknown no 1506 yes no unknown 5 may 92 1 -1 0 unknown no
4 33 unknown single unknown no 1 no no unknown 5 may 198 1 -1 0 unknown no

Analicemos algunas funciones utiles de la indexación explicita:

  • df.set_index(); Este método se usa para establecer una o más columnas del DataFrame como su índice.

# Establecer la columna 'job' como índice
# Ejemplo
  • df.reset_index():Este método se usa para restablecer el índice del DataFrame, devolviendo los índices actuales a columnas y creando un nuevo índice numérico predeterminado. Si usas el parámetro drop=True indica que se debe eliminar la columna de índice original en lugar de moverla a una columna.

# Ejemplo
  • df.sort_index(): Este método ordena las filas del DataFrame en función del índice.

import pandas as pd
from ydata_profiling import ProfileReport
filename = 'C:/GitHub/Datos/datamanip/bank/bank-full.csv'
df = pd.read_csv(filename,sep=';')

profile = ProfileReport(df,title='Informe de los datos', explorative = True)
profile.to_notebook_iframe()
profile.to_file('C:/Users/cdeor/OneDrive/Escritorio/Informe_datos.html')

En conclusión, el uso de índices explícitos en Python es una técnica poderosa que permite un control detallado sobre la manipulación de datos. Ya sea en estructuras simples como listas o en análisis más complejos utilizando pandas, el conocimiento y uso adecuado de índices explícitos puede mejorar significativamente la eficiencia y claridad de tu código.

Visualización sencilla de datos#

Para el desarrollo de las visualización trabajaremos con datos sobre los almacenes Walmart, que es un cadena de grande almacenes de Ewa.

_images/walmart.png

El conjunto de datos completos lo puede encontrar este link. Trabajaremos un subconjunto de datos contiene las ventas semanales en dolares, cada tienda tiene un número de identificación y un tipo de tienda específico, las ventas estan separadas por ID de departamento. Junto con las ventas hay variables como si fue de vacaciones o no, la temperatura media durante la semana en esa localidad, el tiempo medio del combustible en dolares por litro esa semana y la tasa de desempleo de esa semana

Aquí tienes una explicación de las variables en el conjunto de datos de ventas proporcionado:

  • Unnamed: Columna de índice que parece haber sido incluida al guardar el archivo. No es una variable significativa.

  • store: Identificador del número de la tienda.

  • type: Tipo de tienda, representado por una letra (por ejemplo, “A”, “B”, etc.).

  • department: Identificador del número de departamento dentro de la tienda.

  • date: Fecha en la que se registró la venta.

  • weekly_sales: Ventas semanales en USD registradas en esa tienda y departamento específicos.

  • is_holiday: Variable booleana que indica si la fecha corresponde a un día festivo o no. Los valores son “True” o “False”.

  • temperature_c: Temperatura en grados Celsius en la fecha registrada.

  • fuel_price_usd_per_l: Precio del combustible en dólares estadounidenses por litro en la fecha registrada.

  • unemployment: Tasa de desempleo en la fecha registrada.

Carguemos el conjunto de datos:

# Ejemplo
# Renombrar una columna
# Ejemplo
# Ejemplo

Matplotlib es especialmente útil cuando necesitas crear gráficos personalizados y detallados, y es una herramienta esencial para cualquier persona que trabaje con visualización de datos en Python. Haremos unas gráficas univariadas

Histograma#

Un histograma es una representación gráfica que muestra la distribución de una variable continua. Se divide el rango de valores en intervalos (bins) y se cuenta cuántos valores caen en cada intervalo.

Características del histograma

  • Ideal para visualizar la forma de la distribución de los datos.

  • Ayuda a identificar la simetría, la dispersión, y la presencia de outliers.

  • El número de bins afecta la interpretación; demasiados o muy pocos bins pueden ocultar patrones importantes.

  • Permite una fácil visualización de la distribución de datos.

  • Útil para identificar la presencia de sesgos en los datos.

  • No es útil para datos categóricos.

# importar matplotlib
import matplotlib.pyplot as plt

# Histograma de las ventas semanales
# Ejemplo
# Otra forma
# Ejemplo
import warnings
warnings.filterwarnings("ignore")
# Ejemplo
# Ejemplo

Densidad#

Una gráfica de densidad es una representación gráfica suave de la distribución de una variable continua. Se basa en la estimación de la función de densidad de probabilidad (KDE, por sus siglas en inglés), lo que permite visualizar la forma general de la distribución sin depender de intervalos rígidos como en los histogramas.

Características de la gráfica de densidad

  • Ideal para visualizar la forma suave de la distribución de los datos.

  • Útil para comparar distribuciones entre varios grupos.

  • No requiere la definición de bins, a diferencia del histograma.

  • Permite identificar modas (picos), simetría, y presencia de sesgos.

  • Es sensible al parámetro de suavizado (bandwidth), el cual afecta la forma de la curva.

  • A diferencia del histograma, muestra una curva continua.

  • No es útil para datos categóricos.

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde

# Estimación de densidad usando KDE
kde = gaussian_kde(df['fuel_price_usd_per_l'].dropna())
x_vals = np.linspace(min(data), max(data), 1000)
y_vals = kde(x_vals)

# Gráfico
plt.figure(figsize=(8, 4))
plt.plot(x_vals, y_vals, color='blue', lw=2, label='Densidad KDE')
plt.fill_between(x_vals, y_vals, alpha=0.3, color='blue')
plt.title('Gráfica de densidad de precio del combustible (Matplotlib + SciPy)')
plt.xlabel('Precio USD por litro')
plt.ylabel('Densidad')
plt.legend()
plt.grid(True)
plt.show()

Histograma con función de densidad#

Un histograma con función de densidad combina la representación clásica del histograma (que agrupa los datos en intervalos) con una curva de densidad suave (estimación KDE). Esta combinación permite visualizar tanto la frecuencia aproximada de los valores como la forma general de la distribución de los datos.

Características del histograma con función de densidad

  • Combina la vista detallada del histograma con la suavidad de la curva de densidad.

  • Útil para observar la frecuencia de los datos junto con la tendencia general.

  • Permite detectar sesgos, modas, simetría, y posibles valores atípicos.

  • El número de bins influye en la forma del histograma; la curva de densidad ayuda a suavizar esa variabilidad.

  • La curva KDE puede verse afectada por el parámetro de suavizado (bandwidth).

  • Ideal para explorar la distribución de variables continuas.

# KDE
kde = gaussian_kde(df['fuel_price_usd_per_l'].dropna())
x_vals = np.linspace(min(data), max(data), 1000)
y_vals = kde(x_vals)

# Gráfico
plt.figure(figsize=(8, 4))
plt.hist(data, bins=30, density=True, alpha=0.4, color='skyblue', label='Histograma')
plt.plot(x_vals, y_vals, color='darkblue', lw=2, label='Densidad KDE')
plt.title('Histograma con curva de densidad')
plt.xlabel('Precio USD por litro')
plt.ylabel('Densidad')
plt.legend()
plt.grid(True)
plt.show()
_images/dfae611dd1b0e72b799b27c84d992c9a738aed55b908c824aa18be7752f935ec.png
  • Una transformación logarítmica ayuda a identificar más tendencias. Por ejemplo, en el siguiente gráfico, el eje muestra los valores transformados en logaritmos de la variable del precio, y vemos que hay dos o más picos que indican el precio de la gasolina por litro

# Aplicar logaritmo y eliminar valores no válidos
log_data = np.log(df['fuel_price_usd_per_l'].dropna())

# KDE
kde = gaussian_kde(log_data)
x_vals = np.linspace(min(log_data), max(log_data), 1000)
y_vals = kde(x_vals)

# Gráfico
plt.figure(figsize=(8, 4))
plt.hist(log_data, bins=30, density=True, alpha=0.4, color='skyblue', label='Histograma (log)')
plt.plot(x_vals, y_vals, color='darkblue', lw=2, label='Densidad KDE')
plt.title('Histograma con curva de densidad (Log precios)')
plt.xlabel('Log(Precio USD por litro)')
plt.ylabel('Densidad')
plt.legend()
plt.grid(True)
plt.show()
_images/a6dff50718e97b4468cc1e78fccfe31b6a09ca8c9cf960bcbbc1ad8e527ffa4d.png

Cajas y bigotes#

Un gráfico de cajas y bigotes visualiza la distribución de un conjunto de datos, mostrando la mediana y los cuartiles, así como los posibles outliers.

Características de la cajas y bigotes

  • Caja: Representa el rango intercuartil (IQR), es decir, el 50% central de los datos, entre el primer y el tercer cuartil (Q1 y Q3).

  • Línea dentro de la caja: Representa la mediana (Q2) de los datos.

  • Bigotes: Se extienden desde los cuartiles hasta el valor más pequeño y el más grande dentro de 1.5 veces el IQR. Los valores fuera de este rango se consideran outliers y se marcan como puntos individuales.

  • Outliers: Valores que caen fuera de los bigotes y son indicados por puntos individuales.

Ventajas

  • Resúmenes concisos: Muestra un resumen estadístico claro en un formato gráfico compacto.

  • Detección de outliers: Facilita la identificación de valores atípicos o extremos.

  • Comparación entre grupos: Permite comparar la distribución de datos entre diferentes grupos o categorías de manera efectiva.

# Ejemplo

Barras#

Una gráfica de barras se utiliza para mostrar y comparar cantidades entre diferentes categorías. Cada barra representa una categoría, y su altura es proporcional al valor que representa.

Características de las barras

  • Adecuada para datos categóricos.

  • Las barras pueden organizarse horizontal o verticalmente. Fácil de interpretar y comparar diferentes categorías.

  • Proporciona una clara visualización de las diferencias entre categorías.

  • Fácil de leer e interpretar, incluso con muchas categorías.

# Contar el tipo de tienda
# Ejemplo

Circulares#

Un diagrama circular (o gráfico de pastel) es una representación gráfica que muestra la proporción de diferentes categorías dentro de un conjunto de datos como segmentos de un círculo. Cada segmento del círculo representa una categoría y su tamaño es proporcional a su frecuencia o porcentaje en relación con el total.

Características del diagrama circular

  • Segmentos: Cada porción del círculo corresponde a una categoría y muestra su proporción respecto al total.

  • Proporciones: La suma de todos los segmentos representa el 100% del conjunto de datos.

  • Etiquetas: A menudo se etiquetan los segmentos con nombres de categorías y porcentajes.

Ventajas

  • Visualización clara: Facilita la comprensión de las proporciones de las categorías en un solo vistazo.

  • Comparación intuitiva: Permite comparar rápidamente las partes del total.

  • Atractivo visual: Los gráficos de pastel son visualmente atractivos y pueden ser útiles para presentaciones y informes.

Desventaja

  • Dificultad con muchas categorías: No es ideal para conjuntos de datos con muchas categorías, ya que los segmentos pueden volverse difíciles de distinguir.

Para crear un diagrama circular debemos tener en cuenta los siguientes parámetros:

plt.pie(tipo, labels=tipo.index, autopct='%1.1f%%', startangle=140, colors=plt.cm.Paired(range(len(tipo)))) 

genera el diagrama circular:

  • tipo contiene los valores de conteo de cada categoría.

  • labels=tipo.index asigna etiquetas a cada segmento del gráfico.

  • autopct='%1.1f%%' muestra los porcentajes en cada segmento.

  • startangle=140 rota el gráfico para una mejor presentación.

  • colors=plt.cm.Paired(range(len(tipo))) usa un mapa de colores para diferenciar los segmentos.

# Ejemplo
_images/f983363e9689c8e1d34fb83c34a40afa8caf7bbb7f6be0d701fa4baf0e936ea3.png

Ahora haremos unas gráficas bivariadas.

Lineas#

Una gráfica de líneas conecta una serie de puntos de datos con líneas, generalmente utilizada para mostrar cambios o tendencias a lo largo del tiempo.

Características del diagrama de lineas

  • Ideal para series temporales.

  • Muestra la tendencia general de los datos.

  • Puede incluir múltiples líneas para comparar diferentes series de datos.

Ventajas

  • Excelente para visualizar tendencias a lo largo del tiempo.

  • Permite comparar fácilmente varias series de datos.

Desventajas

  • Puede volverse confusa si se incluyen demasiadas líneas.

  • No es adecuada para datos categóricos.

# Ejemplo

Dispersión (Scatter Plots)#

Una gráfica de dispersión muestra la relación entre dos variables numéricas mediante puntos dispersos en un plano cartesiano.

Características del diagrama de dispersión

  • Muestra cómo se correlacionan dos variables.

  • Los patrones de dispersión pueden indicar la relación entre las variables, como linealidad o agrupaciones.

  • Cada punto representa una observación individual.

Ventajas

  • Ideal para identificar relaciones o correlaciones entre dos variables.

  • Permite visualizar la distribución y posibles outliers.

Desventajas

  • No es adecuada para más de dos variables sin técnicas adicionales.

  • Si hay demasiados puntos, puede volverse difícil de interpretar.

# Crear una gráfica de dispersión de wee
# Ejemplo

Histogramas con variable categórica#

Para hacer estos histogramas debemos tener una variable numérica según una variable categórica

# Ejemplo

Cajas y bigotes con variable categórica#

Para hacer estos diagramas de cajas y bigotes debemos tener una variable numérica según una variable categórica

# Ejemplo

Diagrama de barras con variables categóricas#

Realizaremos un diagrama de barras con dos variables categóricas

# Ejemplo

Para exportar las gráficas en formato png. Usamos savefig:

Este módulo ha proporcionado una base sólida en la importación, manipulación y visualización de datos en Python. Las habilidades adquiridas permitirán crear visualizaciones efectivas que faciliten la interpretación y comunicación de los datos, y la capacidad de manipular y preparar datos adecuadamente es esencial para realizar análisis significativos. La combinación de pandas para la manipulación de datos y Matplotlib para la visualización forma una potente herramienta en el análisis de datos y ciencia de datos.

Diagrama hexagonal#

Existe una versión más elegante de los gráficos de dispersión, llamada hexagonal binning plot (hexbin plot). En este ejercicio, utilizaremos Seaborn para crear una gráfica de dispersión hexagonal (Hexbin Plot) que muestre la relación entre las ventas semanales (weekly_sales) y el precio de la gasolina en USD por litro (fuel_price_usd_per_l). Este gráfico es útil para representar la densidad de datos cuando estos se superponen.

  1. Importemos las bibliotecas necesarias:

import seaborn as sns
import matplotlib.pyplot as plt
  1. Usaremos sns.scatterplot para crear una gráfica de dispersión, y añadiremos un esquema de color personalizado para mejorar la visualización.

import warnings
warnings.filterwarnings("ignore", category=FutureWarning)

# Ejemplo

Observación

  • Este gráfico utiliza celdas hexagonales para representar la densidad de puntos en áreas donde las ventas semanales y el precio de la gasolina están más concentrados.

  • El histograma en los bordes superior y derecho muestra la variabilidad individual de cada variable (ventas semanales y precio de la gasolina, respectivamente).

Diagrama de contorno#

Los gráficos de contorno son útiles cuando los puntos de datos están densamente poblados en ciertas áreas, ya que muestran la concentración de los datos mediante líneas de contorno. En este ejercicio, crearemos un gráfico de contorno para analizar la relación entre las ventas semanales (weekly_sales) y el precio de la gasolina en USD por litro (fuel_price_usd_per_l).

  1. Importar las bibliotecas necesarias:

import seaborn as sns
import matplotlib.pyplot as plt
  1. Utilizaremos el método sns.kdeplot() para generar un gráfico de contorno con las ventas semanales y el precio de la gasolina, y rellenar las áreas con gradientes de color para reflejar la densidad de puntos.

import warnings
warnings.filterwarnings("ignore", category=FutureWarning)

# Ejemplo